package com.klikmee.sms.cef.bulk;

import java.io.IOException;
import java.text.MessageFormat;
import java.util.Hashtable;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.log4j.Logger;

public abstract class HttpBulkSender implements BulkSender<String> {

	public static final String		SEND_CONTEXT	= "HttpBulkSender.send";
	/**
	 * Ref to the log impl
	 */
	private Logger					logger			= Logger.getLogger( HttpBulkSender.class );
	/**
	 * URL to submit bulk request to
	 */
	protected String				url				= null;
	/**
	 * Handler for http response
	 */
	private HttpBulkResponseHandler	handler			= null;

	@Override
	public String send(Hashtable<BulkParams, Object> params) throws SendBulkException {
		HttpClient httpClient = new HttpClient();
		HttpMethod method = createHttpMethod( params );

		try {
			logger.debug( MessageFormat.format( "Trying to execute bulk request [{0}]", method.getQueryString() ) );
			// execute http method
			int statusCode = httpClient.executeMethod( method );
			// if
			if (statusCode != HttpStatus.SC_OK) {
				throw SendBulkException.create( this.url, new RuntimeException( MessageFormat.format( "Error while invoking http URL [{0}]", method.getPath() ) ), null );
			}
			// forward http response to handler
			byte[] responseBody = method.getResponseBody();
			// convert response to string
			String response = new String( responseBody );
			// invoke hook
			afterBulkMessageSent( response, params );

			return response;
		}
		catch (HttpException e) {
			logger.fatal( e );
			throw SendBulkException.create( this.url, e, HttpBulkSender.SEND_CONTEXT );
		}
		catch (IOException e) {
			logger.fatal( e );
			throw SendBulkException.create( this.url, e, HttpBulkSender.SEND_CONTEXT );
		}
		finally {
			method.releaseConnection();
		}

	}

	/**
	 * Hook method invoked after bulk message was sent
	 * 
	 * @param string
	 *            HTTP response body
	 * @param params
	 *            bulk message params
	 */
	protected void afterBulkMessageSent(String string, Hashtable<BulkParams, Object> params) {
	}

	/**
	 * Creates @see HttpMethod object based on params
	 * 
	 * @param params
	 *            http method params containing http request values
	 * @return instance of {@link HttpMethod} object
	 * 
	 */
	public HttpMethod createHttpMethod(Hashtable<BulkParams, Object> params) {
		HttpMethod method = new GetMethod( url );

		// create query string for http request
		NameValuePair[] queryStringParams = createQueryStringParams( params );
		method.setQueryString( queryStringParams );
		return method;
	}

	public abstract NameValuePair[] createQueryStringParams(Hashtable<BulkParams, Object> params);

	public void setUrl(String url) {
		this.url = url;
	}

	public void setHandler(HttpBulkResponseHandler handler) {
		this.handler = handler;
	}
}
